use axum::http::StatusCode;
use axum::response::IntoResponse;
use axum::{Json, extract::Query};
use my_rust_core::shared::serde_json_helper::ExtractJsonValue;
use serde::Deserialize;
use serde_json::{Value, json};
use serde_with::NoneAsEmptyString;

pub async fn index() -> impl IntoResponse {
    super::shared::get_data_response(json!({
      "name": "users"
    }))
}

#[serde_with::serde_as]
#[derive(Debug, Deserialize)]
pub struct Pagination {
    #[serde(rename = "pageSize")]
    #[serde_as(as = "NoneAsEmptyString")]
    #[serde(default)]
    page_size: Option<usize>,
}

pub async fn list(Query(param): Query<Pagination>) -> Json<Value> {
    Json(json!({
      "name": "John Doe",
        "age": 43,
        "phones": [
            "+44 1234567",
            "+44 2345678",
        ],
        "pageSize": param.page_size,
    }))
}

/// Example of getting data in [Json<Value>] instead of predefined struct.
/// But it only works for post with json format data in request body.
pub async fn update_by_name(Json(payload): Json<Value>) -> Json<Value> {
    let name = payload.get_str_value("name");

    Json(json!({
        "name": name,
    }))
}

#[serde_with::serde_as]
#[derive(Debug, Deserialize)]
pub struct User {
    #[serde_as(as = "NoneAsEmptyString")]
    #[serde(default)]
    username: Option<String>,
}

pub async fn add(Json(user): Json<User>) -> impl IntoResponse {
    (
        StatusCode::CREATED,
        Json(json!({
            "username": user.username,
        })),
    )
}
